/**
 * Service Worker - 资源缓存策略
 * Story 4: Task 5 - Service Worker缓存实现
 */

const CACHE_VERSION = 'v1'
const CACHE_NAME = `ai-writing-${CACHE_VERSION}`

// 需要预缓存的静态资源
const STATIC_CACHE_URLS = [
  '/',
  '/index.html',
  '/manifest.json',
]

// 缓存策略配置
const CACHE_STRATEGIES = {
  CACHE_FIRST: 'cache-first',
  NETWORK_FIRST: 'network-first',
  STALE_WHILE_REVALIDATE: 'stale-while-revalidate',
}

// 资源类型到缓存策略的映射
const RESOURCE_CACHE_STRATEGY = {
  // JavaScript和CSS使用缓存优先
  js: CACHE_STRATEGIES.CACHE_FIRST,
  css: CACHE_STRATEGIES.CACHE_FIRST,
  // 图片使用缓存优先
  image: CACHE_STRATEGIES.CACHE_FIRST,
  // 字体使用缓存优先
  font: CACHE_STRATEGIES.CACHE_FIRST,
  // API请求使用网络优先
  api: CACHE_STRATEGIES.NETWORK_FIRST,
  // 其他资源使用Stale-While-Revalidate
  other: CACHE_STRATEGIES.STALE_WHILE_REVALIDATE,
}

// 获取资源类型
function getResourceType(url) {
  if (url.includes('/api/')) return 'api'
  if (/\.(js|mjs)$/i.test(url)) return 'js'
  if (/\.css$/i.test(url)) return 'css'
  if (/\.(jpg|jpeg|png|gif|webp|svg|ico)$/i.test(url)) return 'image'
  if (/\.(woff|woff2|ttf|otf|eot)$/i.test(url)) return 'font'
  return 'other'
}

// 获取缓存策略
function getCacheStrategy(url) {
  const type = getResourceType(url)
  return RESOURCE_CACHE_STRATEGY[type] || CACHE_STRATEGIES.STALE_WHILE_REVALIDATE
}

/**
 * 安装Service Worker
 */
self.addEventListener('install', (event) => {
  console.log('[SW] Installing Service Worker...')

  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      console.log('[SW] Precaching static resources')
      return cache.addAll(STATIC_CACHE_URLS)
    }).then(() => {
      // 跳过等待，立即激活
      return self.skipWaiting()
    })
  )
})

/**
 * 激活Service Worker
 */
self.addEventListener('activate', (event) => {
  console.log('[SW] Activating Service Worker...')

  event.waitUntil(
    // 清理旧缓存
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames
          .filter((name) => name !== CACHE_NAME)
          .map((name) => {
            console.log('[SW] Deleting old cache:', name)
            return caches.delete(name)
          })
      )
    }).then(() => {
      // 立即控制所有客户端
      return self.clients.claim()
    })
  )
})

/**
 * 拦截Fetch请求
 */
self.addEventListener('fetch', (event) => {
  const { request } = event
  const url = new URL(request.url)

  // 只处理同源请求或特定的跨域请求
  if (url.origin !== self.location.origin && !shouldCacheCrossOrigin(url)) {
    return
  }

  const strategy = getCacheStrategy(request.url)

  // 根据策略处理请求
  switch (strategy) {
    case CACHE_STRATEGIES.CACHE_FIRST:
      event.respondWith(cacheFirst(request))
      break
    case CACHE_STRATEGIES.NETWORK_FIRST:
      event.respondWith(networkFirst(request))
      break
    case CACHE_STRATEGIES.STALE_WHILE_REVALIDATE:
      event.respondWith(staleWhileRevalidate(request))
      break
    default:
      event.respondWith(fetch(request))
  }
})

/**
 * Cache-First策略：优先使用缓存
 * 适用于：JS、CSS、图片、字体等静态资源
 */
async function cacheFirst(request) {
  const cached = await caches.match(request)

  if (cached) {
    return cached
  }

  try {
    const response = await fetch(request)

    // 只缓存成功的GET请求
    if (response.ok && request.method === 'GET') {
      const cache = await caches.open(CACHE_NAME)
      cache.put(request, response.clone())
    }

    return response
  } catch (error) {
    console.error('[SW] Fetch failed:', error)

    // 返回离线页面或默认响应
    return new Response('Offline', {
      status: 503,
      statusText: 'Service Unavailable',
    })
  }
}

/**
 * Network-First策略：优先使用网络
 * 适用于：API请求
 */
async function networkFirst(request) {
  try {
    const response = await fetch(request)

    // 缓存成功的GET请求
    if (response.ok && request.method === 'GET') {
      const cache = await caches.open(CACHE_NAME)
      cache.put(request, response.clone())
    }

    return response
  } catch (error) {
    console.error('[SW] Network request failed, trying cache:', error)

    // 网络失败时尝试从缓存获取
    const cached = await caches.match(request)

    if (cached) {
      return cached
    }

    // 如果缓存也没有，返回错误响应
    return new Response(
      JSON.stringify({ error: 'Network error and no cache available' }),
      {
        status: 503,
        statusText: 'Service Unavailable',
        headers: { 'Content-Type': 'application/json' },
      }
    )
  }
}

/**
 * Stale-While-Revalidate策略：返回缓存并在后台更新
 * 适用于：次要资源，平衡性能和新鲜度
 */
async function staleWhileRevalidate(request) {
  const cached = await caches.match(request)

  // 后台更新缓存
  const fetchPromise = fetch(request).then(async (response) => {
    if (response.ok && request.method === 'GET') {
      const cache = await caches.open(CACHE_NAME)
      cache.put(request, response.clone())
    }
    return response
  }).catch((error) => {
    console.error('[SW] Background fetch failed:', error)
  })

  // 如果有缓存，立即返回；否则等待网络请求
  return cached || fetchPromise
}

/**
 * 判断是否应该缓存跨域请求
 */
function shouldCacheCrossOrigin(url) {
  // 可以添加白名单域名
  const allowedOrigins = [
    'https://fonts.googleapis.com',
    'https://fonts.gstatic.com',
    'https://cdn.jsdelivr.net',
  ]

  return allowedOrigins.some((origin) => url.origin === origin)
}

/**
 * 消息处理
 */
self.addEventListener('message', (event) => {
  if (event.data === 'SKIP_WAITING') {
    self.skipWaiting()
  }

  if (event.data === 'CLEAR_CACHE') {
    caches.delete(CACHE_NAME).then(() => {
      event.ports[0].postMessage({ success: true })
    })
  }
})

console.log('[SW] Service Worker script loaded')
